"""
文件名: exceptions.py
描述: 自定义异常类模块

本模块包含以下主要功能：
1. 基础异常类定义
2. 认证和授权相关异常
3. YouTube API相关异常
4. 数据验证异常
5. 业务逻辑异常

依赖模块:
   - typing: 类型注解
   - fastapi: HTTP异常

使用示例:
   >>> from src.utils.exceptions import AuthenticationException
   >>> raise AuthenticationException("用户未登录")
   >>> 
   >>> try:
   ...     # 调用YouTube API
   ...     pass
   >>> except YouTubeAPIException as e:
   ...     logger.error(f"YouTube API错误: {e}")

注意事项:
   - 异常信息要对用户友好
   - 包含足够的调试信息
   - 不暴露敏感系统信息
   - 支持国际化

作者: AI助手
创建日期: 2024-06-27
最后修改: 2024-06-27
版本: 1.0.0
"""

from typing import Any, Dict, Optional


class YouTubeManagerException(Exception):
    """
    YouTube管理器基础异常类
    
    所有自定义异常的基类，提供统一的异常处理接口
    """
    
    def __init__(
        self,
        message: str,
        code: Optional[str] = None,
        details: Optional[Dict[str, Any]] = None,
    ):
        """
        初始化异常
        
        Args:
            message: 异常消息
            code: 错误代码
            details: 详细信息字典
        """
        self.message = message
        self.code = code or self.__class__.__name__
        self.details = details or {}
        super().__init__(message)
    
    def __str__(self) -> str:
        return f"[{self.code}] {self.message}"
    
    def __repr__(self) -> str:
        return f"{self.__class__.__name__}(message='{self.message}', code='{self.code}')"
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式，便于API返回"""
        return {
            "error": True,
            "code": self.code,
            "message": self.message,
            "details": self.details,
        }


class AuthenticationException(YouTubeManagerException):
    """
    认证异常
    
    用户身份验证失败时抛出此异常
    """
    
    def __init__(
        self,
        message: str = "认证失败",
        code: str = "AUTHENTICATION_FAILED",
        details: Optional[Dict[str, Any]] = None,
    ):
        super().__init__(message, code, details)


class AuthorizationException(YouTubeManagerException):
    """
    授权异常
    
    用户权限不足时抛出此异常
    """
    
    def __init__(
        self,
        message: str = "权限不足",
        code: str = "AUTHORIZATION_FAILED", 
        details: Optional[Dict[str, Any]] = None,
    ):
        super().__init__(message, code, details)


class TokenExpiredException(AuthenticationException):
    """
    令牌过期异常
    
    访问令牌或刷新令牌过期时抛出此异常
    """
    
    def __init__(
        self,
        message: str = "令牌已过期",
        code: str = "TOKEN_EXPIRED",
        details: Optional[Dict[str, Any]] = None,
    ):
        super().__init__(message, code, details)


class InvalidTokenException(AuthenticationException):
    """
    无效令牌异常
    
    令牌格式错误或验证失败时抛出此异常
    """
    
    def __init__(
        self,
        message: str = "无效的令牌",
        code: str = "INVALID_TOKEN",
        details: Optional[Dict[str, Any]] = None,
    ):
        super().__init__(message, code, details)


class YouTubeAPIException(YouTubeManagerException):
    """
    YouTube API异常
    
    调用YouTube API失败时抛出此异常
    """
    
    def __init__(
        self,
        message: str,
        code: str = "YOUTUBE_API_ERROR",
        api_error_code: Optional[str] = None,
        quota_exceeded: bool = False,
        details: Optional[Dict[str, Any]] = None,
    ):
        """
        初始化YouTube API异常
        
        Args:
            message: 异常消息
            code: 错误代码
            api_error_code: YouTube API返回的错误代码
            quota_exceeded: 是否为配额超限错误
            details: 详细信息
        """
        details = details or {}
        if api_error_code:
            details["api_error_code"] = api_error_code
        details["quota_exceeded"] = quota_exceeded
        
        super().__init__(message, code, details)
        self.api_error_code = api_error_code
        self.quota_exceeded = quota_exceeded


class QuotaExceededException(YouTubeAPIException):
    """
    配额超限异常
    
    YouTube API配额用完时抛出此异常
    """
    
    def __init__(
        self,
        message: str = "YouTube API配额已用完",
        code: str = "QUOTA_EXCEEDED",
        details: Optional[Dict[str, Any]] = None,
    ):
        super().__init__(message, code, quota_exceeded=True, details=details)


class ValidationException(YouTubeManagerException):
    """
    数据验证异常
    
    输入数据验证失败时抛出此异常
    """
    
    def __init__(
        self,
        message: str,
        field: Optional[str] = None,
        value: Optional[Any] = None,
        code: str = "VALIDATION_ERROR",
        details: Optional[Dict[str, Any]] = None,
    ):
        """
        初始化验证异常
        
        Args:
            message: 异常消息
            field: 验证失败的字段名
            value: 验证失败的值
            code: 错误代码
            details: 详细信息
        """
        details = details or {}
        if field:
            details["field"] = field
        if value is not None:
            details["value"] = str(value)
        
        super().__init__(message, code, details)
        self.field = field
        self.value = value


class DatabaseException(YouTubeManagerException):
    """
    数据库异常
    
    数据库操作失败时抛出此异常
    """
    
    def __init__(
        self,
        message: str,
        operation: Optional[str] = None,
        code: str = "DATABASE_ERROR",
        details: Optional[Dict[str, Any]] = None,
    ):
        """
        初始化数据库异常
        
        Args:
            message: 异常消息
            operation: 失败的数据库操作
            code: 错误代码
            details: 详细信息
        """
        details = details or {}
        if operation:
            details["operation"] = operation
        
        super().__init__(message, code, details)
        self.operation = operation


class CacheException(YouTubeManagerException):
    """
    缓存异常
    
    Redis缓存操作失败时抛出此异常
    """
    
    def __init__(
        self,
        message: str,
        operation: Optional[str] = None,
        key: Optional[str] = None,
        code: str = "CACHE_ERROR",
        details: Optional[Dict[str, Any]] = None,
    ):
        """
        初始化缓存异常
        
        Args:
            message: 异常消息
            operation: 失败的缓存操作
            key: 缓存键
            code: 错误代码
            details: 详细信息
        """
        details = details or {}
        if operation:
            details["operation"] = operation
        if key:
            details["key"] = key
        
        super().__init__(message, code, details)
        self.operation = operation
        self.key = key


class ConfigurationException(YouTubeManagerException):
    """
    配置异常
    
    配置错误或缺失时抛出此异常
    """
    
    def __init__(
        self,
        message: str,
        config_key: Optional[str] = None,
        code: str = "CONFIGURATION_ERROR",
        details: Optional[Dict[str, Any]] = None,
    ):
        """
        初始化配置异常
        
        Args:
            message: 异常消息
            config_key: 配置键名
            code: 错误代码
            details: 详细信息
        """
        details = details or {}
        if config_key:
            details["config_key"] = config_key
        
        super().__init__(message, code, details)
        self.config_key = config_key


class RateLimitException(YouTubeManagerException):
    """
    速率限制异常
    
    API调用频率超限时抛出此异常
    """
    
    def __init__(
        self,
        message: str = "API调用频率超限",
        retry_after: Optional[int] = None,
        code: str = "RATE_LIMIT_EXCEEDED",
        details: Optional[Dict[str, Any]] = None,
    ):
        """
        初始化速率限制异常
        
        Args:
            message: 异常消息
            retry_after: 建议重试间隔（秒）
            code: 错误代码
            details: 详细信息
        """
        details = details or {}
        if retry_after:
            details["retry_after"] = retry_after
        
        super().__init__(message, code, details)
        self.retry_after = retry_after


class ServiceUnavailableException(YouTubeManagerException):
    """
    服务不可用异常
    
    外部服务不可用时抛出此异常
    """
    
    def __init__(
        self,
        message: str = "服务暂时不可用",
        service: Optional[str] = None,
        code: str = "SERVICE_UNAVAILABLE",
        details: Optional[Dict[str, Any]] = None,
    ):
        """
        初始化服务不可用异常
        
        Args:
            message: 异常消息
            service: 服务名称
            code: 错误代码
            details: 详细信息
        """
        details = details or {}
        if service:
            details["service"] = service
        
        super().__init__(message, code, details)
        self.service = service


class SearchException(YouTubeManagerException):
    """
    搜索异常
    
    搜索操作失败时抛出此异常
    """
    
    def __init__(
        self,
        message: str = "搜索操作失败",
        query: Optional[str] = None,
        search_type: Optional[str] = None,
        code: str = "SEARCH_ERROR",
        details: Optional[Dict[str, Any]] = None,
    ):
        """
        初始化搜索异常
        
        Args:
            message: 异常消息
            query: 搜索查询
            search_type: 搜索类型
            code: 错误代码
            details: 详细信息
        """
        details = details or {}
        if query:
            details["query"] = query
        if search_type:
            details["search_type"] = search_type
        
        super().__init__(message, code, details)
        self.query = query
        self.search_type = search_type


# 异常代码常量
class ErrorCodes:
    """错误代码常量"""
    
    # 认证相关
    AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED"
    AUTHORIZATION_FAILED = "AUTHORIZATION_FAILED"
    TOKEN_EXPIRED = "TOKEN_EXPIRED"
    INVALID_TOKEN = "INVALID_TOKEN"
    
    # YouTube API相关
    YOUTUBE_API_ERROR = "YOUTUBE_API_ERROR"
    QUOTA_EXCEEDED = "QUOTA_EXCEEDED"
    INVALID_CREDENTIALS = "INVALID_CREDENTIALS"
    
    # 数据验证相关
    VALIDATION_ERROR = "VALIDATION_ERROR"
    MISSING_REQUIRED_FIELD = "MISSING_REQUIRED_FIELD"
    INVALID_FORMAT = "INVALID_FORMAT"
    
    # 系统相关
    DATABASE_ERROR = "DATABASE_ERROR"
    CACHE_ERROR = "CACHE_ERROR"
    CONFIGURATION_ERROR = "CONFIGURATION_ERROR"
    SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE"
    RATE_LIMIT_EXCEEDED = "RATE_LIMIT_EXCEEDED"


# 导出主要接口
__all__ = [
    "YouTubeManagerException",
    "AuthenticationException",
    "AuthorizationException",
    "TokenExpiredException",
    "InvalidTokenException",
    "YouTubeAPIException",
    "QuotaExceededException",
    "ValidationException",
    "DatabaseException",
    "CacheException",
    "ConfigurationException",
    "RateLimitException",
    "ServiceUnavailableException",
    "SearchException",
    "ErrorCodes",
]